#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <stdarg.h>

/**
 * 对于X86（32bit）：函数形参存放在栈区，入栈顺序为从右到左，即最后一个参数先入栈，第一个参数最后入栈
 * 
 * 在Linux下，栈由低字节向高字节生长：
 * 高地址
 * +------------------+
 * | 返回地址         |
 * +------------------+
 * | 第一个参数 (a)   | <-- ebp + 8
 * +------------------+
 * | 第二个参数 (b)   | <-- ebp + 12
 * +------------------+
 * | 第三个参数 (c)   | <-- ebp + 16
 * +------------------+
 * 低地址
 * 
 * 在Windows下，栈由高字节向低字节生长；
 */
void fun1(int a, int b, int c) {
    int x = 1;
    int y = 2;
    int z = 3;
    printf("\t %10s %20s\n", "variable", "address");
    printf("\t %10s %20p\n", "a", &a);
    printf("\t %10s %20p\n", "b", &b);
    printf("\t %10s %20p\n", "c", &c);

    printf("\t %10s %20p\n", "x", &x);
    printf("\t %10s %20p\n", "y", &y);
    printf("\t %10s %20p\n", "z", &z);
}

void fun(int a, int b, int c) {
    int x = 1;
    int y = 2;
    int z = 3;
    printf("\t %10s %20s\n", "variable", "address");
    printf("\t %10s %20p\n", "a", &a);
    printf("\t %10s %20p\n", "b", &b);
    printf("\t %10s %20p\n", "c", &c);

    printf("\t %10s %20p\n", "x", &x);
    printf("\t %10s %20p\n", "y", &y);
    printf("\t %10s %20p\n", "z", &z);

    fun1(x, y, z);
}

void test01() {
    printf("================== %s ==================\n", __FUNCTION__);

    int a = 1, b = 2, c = 3;
    fun(a, b, c);
    printf("\t %10s %20p\n", "fun", fun);
}

/**
 * 可变参数列表
 */
void test02(int a, int b, ...) {
    printf("================== %s ==================\n", __FUNCTION__);
    va_list args;
    va_start(args, b);
    printf("address: a(%p), b(%p), args(%p)\n", &a, &b, &args[0]);

    va_end(args);
}

/**
 * @brief 获取可变参数
 * va_list: 一种类型；
 * va_start: 使其指向可变参数列表的第一个参数；
 * va_arg: 逐个读取参数；
 * va_end: 清理资源；
 * 
 * @param count 
 * @param ... 
 * @return double 
 */
double average(int count, ...) {
    va_list ap;
    va_start(ap, count); // 初始化 ap，指向 count 后的第一个参数

    double sum = 0;
    for (int i = 0; i < count; i++) {
        sum += va_arg(ap, double); // 逐个读取 double 类型参数
    }

    va_end(ap); // 清理
    return sum / count;
}

int main(int argc, char *argv[]) {
    test01();
    printf("\n");
    return 0;
}
